package com.life.ai.server.modules.system.service.impl;

import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.life.ai.server.common.constants.UserConstants;
import com.life.ai.server.framework.redis.annotation.RedisCache;
import com.life.ai.server.framework.redis.annotation.RedisEvict;
import com.life.ai.server.modules.system.entity.SysMenu;
import com.life.ai.server.modules.system.entity.SysRoleMenu;
import com.life.ai.server.modules.system.mapper.SysRoleMenuMapper;
import com.life.ai.server.modules.system.service.SysMenuService;
import com.life.ai.server.modules.system.service.SysRoleMenuService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 角色和菜单关联表 服务实现类
 * </p>
 *
 * @author kylewka
 * @since 2024-06-11
 */
@Service
public class SysRoleMenuServiceImpl extends ServiceImpl<SysRoleMenuMapper, SysRoleMenu> implements SysRoleMenuService {

    @Resource
    private SysMenuService     menuService;
    @Resource
    private SysRoleMenuService roleMenuService;

    /**
     * 获取指定角色的菜单列表
     *
     * @param roleId 角色id
     * @return 菜单列表
     */
    @Override
    public List<SysRoleMenu> listByRoleId(Long roleId) {
        return lambdaQuery().eq(SysRoleMenu::getRoleId, roleId).orderByAsc(SysRoleMenu::getMenuId).list();
    }


    /**
     * 获取指定角色的菜单列表
     *
     * @param roleId 角色id
     * @return 菜单列表
     */
    @RedisCache(name = UserConstants.SYS_MENU_OF_ROLE, keys = "#roleId")
    @Override
    public List<SysMenu> listMenuByRoleId(Long roleId) {
        // 缓存不存在时获取逻辑
        List<SysRoleMenu> roleMenus = lambdaQuery().eq(SysRoleMenu::getRoleId, roleId).list();
        if (CollUtil.isEmpty(roleMenus)) {
            // 当前角色菜单为空
            return new ArrayList<>();
        }
        // 当前角色的菜单列表
        Set<Long> menuIds = CollStreamUtil.toSet(roleMenus, SysRoleMenu::getMenuId);
        return menuService.lambdaQuery().in(SysMenu::getId, menuIds).list();
    }

    /**
     * 获取指定角色的菜单列表
     *
     * @param roleIds 角色ids
     * @return 菜单列表
     */
    @Override
    public List<SysMenu> listByRoleIds(Collection<Long> roleIds) {
        List<SysMenu> roleMenus = new ArrayList<>();
        // 获取所有角色的并集
        roleIds.forEach(roleId -> {
            List<SysMenu> menus = roleMenuService.listMenuByRoleId(roleId);
            roleMenus.addAll(menus);
        });
        // 根据id去重
        return roleMenus.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() ->
                new TreeSet<>(Comparator.comparing(SysMenu::getId))), ArrayList::new));
    }

    /**
     * 保存角色菜单关联关系
     *
     * @param roleId  角色id
     * @param menuIds 菜单ids
     */
    @RedisEvict(name = UserConstants.SYS_MENU_OF_ROLE, keys = "#roleId")
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRoleMenu(Long roleId, List<Long> menuIds) {
        lambdaUpdate().eq(SysRoleMenu::getRoleId, roleId).remove();
        if (CollUtil.isEmpty(menuIds)) {
            return;
        }
        List<SysRoleMenu> roleMenus = CollStreamUtil.toList(menuIds, menuId -> new SysRoleMenu(roleId, menuId));
        this.saveBatch(roleMenus);
    }
}

